package com.bjpowernode.gateway.web.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bjpowernode.gateway.common.enums.OrderStatus;
import com.bjpowernode.gateway.common.enums.PublicStatus;
import com.bjpowernode.gateway.common.utils.HttpUtil;
import com.bjpowernode.gateway.common.utils.KqUtil;
import com.bjpowernode.gateway.common.utils.Pkipair;
import com.bjpowernode.gateway.common.utils.SignUtil;
import com.bjpowernode.gateway.db.domain.*;
import com.bjpowernode.gateway.db.mapper.*;
import com.bjpowernode.gateway.web.model.dto.TradeSelectOrderResultDto;
import com.bjpowernode.gateway.web.model.query.TradeReceiveQuery;
import com.bjpowernode.gateway.web.model.query.TradeSelectOrderQuery;
import com.bjpowernode.gateway.web.service.PaymentService;
import com.bjpowernode.gateway.web.service.TradeService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

/**
 * 实现类
 */
@Service
public class TradeServiceImpl implements TradeService {

    @Resource
    private PayProductMapper payProductMapper;

    @Resource
    private UserPayConfigMapper userPayConfigMapper;

    @Resource
    private SignUtil signUtil;

    @Resource
    private PayWayMapper payWayMapper;

    @Resource
    private UserInfoMapper userInfoMapper;

    @Resource
    private TradeOrderMapper tradeOrderMapper;

    @Resource(name = "KUAIQIAN")
    private PaymentService paymentService;

    @Override
    public List<PayWay> chackPayInfoReturnPayWay(TradeReceiveQuery tradeReceiveQuery, String clientIp) {
        // 先进行 验证
        // 验证支付产品是否存在 , 是否启用
        PayProduct payProduct = payProductMapper
                .selectOne(new LambdaQueryWrapper<PayProduct>()
                        .eq(PayProduct::getProductCode, tradeReceiveQuery.getPayProductCode())
                        .eq(PayProduct::getStatus, PublicStatus.ENABLE.name()));
        if (payProduct == null) {
            throw new RuntimeException("支付产品不存在");
        }
        // 查询该产品对应的支付配置  ---->  主要目的是为了得到  app_secret '商家调用需要签名API的密钥，用作加密',
        UserPayConfig userPayConfig = userPayConfigMapper
                .selectOne(new LambdaQueryWrapper<UserPayConfig>()
                        .eq(UserPayConfig::getUserNo, tradeReceiveQuery.getUserNo())
                        .eq(UserPayConfig::getPayProductCode, tradeReceiveQuery.getPayProductCode())
                        .eq(UserPayConfig::getAppKey, tradeReceiveQuery.getAppKey())
                        .eq(UserPayConfig::getStatus, PublicStatus.ENABLE.name()));
        // 判断 支付配置是否存在
        if (userPayConfig == null) {
            throw new RuntimeException("商户支付配置无效");
        }

        // 验证签名  --->  根据数据生成签名  和原签名进行比较
        boolean check = signUtil.checkSignMsg(tradeReceiveQuery, userPayConfig.getAppSecret());
        if (!check) {
            throw new RuntimeException("签名错误");
        }
        // 验证ip  --->  用户支付配置中的ip地址白名单 -> 判断该ip是否在其中
        String ipListString = userPayConfig.getMerchantServerIp();
        long count = Arrays.stream(ipListString.split(","))
                .filter(clientIp::equals)
                .count();
        if (count == 0) {
            throw new RuntimeException("ip限制");
        }

        // 查询 该支付产品包含的 支付方式 以及对应的 类型
        return payWayMapper.selectList(new LambdaQueryWrapper<PayWay>()
                .eq(PayWay::getPayProductCode, tradeReceiveQuery.getPayProductCode())
                .eq(PayWay::getStatus, PublicStatus.ENABLE.name())
                .orderByAsc(PayWay::getWayCode, PayWay::getTypeCode, PayWay::getSorts));
    }

    @Override
    public TradeSelectOrderResultDto checkHandleSelect(TradeSelectOrderQuery tradeSelectOrderQuery) {
        TradeSelectOrderResultDto tradeSelectOrderResultDto = new TradeSelectOrderResultDto();
        tradeSelectOrderResultDto.setUserNo(tradeSelectOrderQuery.getUserNo());
        tradeSelectOrderResultDto.setOrderNo(tradeSelectOrderQuery.getOrderNo());

        // 验证 是否存在 该商户
        UserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getUserNo, tradeSelectOrderQuery.getUserNo()));
        if (userInfo == null) {
            String code = OrderStatus.NONE.name();
            String msg = "商户不存在";
            tradeSelectOrderResultDto.setCode(code);
            tradeSelectOrderResultDto.setMsg(msg);
            tradeSelectOrderResultDto.setTxNo("");
            return tradeSelectOrderResultDto;
        }

        if (!userInfo.getStatus().equals(PublicStatus.ENABLE.name())) {
            String code = OrderStatus.DISABLE.name();
            String msg = "商户已禁用,请联系管理员";
            tradeSelectOrderResultDto.setCode(code);
            tradeSelectOrderResultDto.setMsg(msg);
            tradeSelectOrderResultDto.setTxNo("");
            return tradeSelectOrderResultDto;
        }

        // 查询 交易订单中是否存在该 交易数据
        TradeOrder tradeOrder = tradeOrderMapper.selectOne(new LambdaQueryWrapper<TradeOrder>().eq(TradeOrder::getUserOrderNo, tradeSelectOrderQuery.getOrderNo()));
        if (tradeOrder == null) {
            String code = OrderStatus.NONE.name();
            String msg = "该订单不存在";
            tradeSelectOrderResultDto.setCode(code);
            tradeSelectOrderResultDto.setMsg(msg);
            tradeSelectOrderResultDto.setTxNo("");
            return tradeSelectOrderResultDto;
        }

        if (tradeOrder.getStatus().equals(OrderStatus.CREATE.name())) {
            // 创建状态 , 去第三方交易平台进行查询
            String queryResult = paymentService.gateWayInitQuery(tradeOrder);
            String code = queryResult;
            String msg = OrderStatus.valueOf(queryResult).getMsg();
            tradeSelectOrderResultDto.setCode(code);
            tradeSelectOrderResultDto.setMsg(msg);
            tradeSelectOrderResultDto.setTxNo(tradeOrder.getTxNo());
            return tradeSelectOrderResultDto;
        } else {
            String code = tradeOrder.getStatus();
            String msg = OrderStatus.valueOf(tradeOrder.getStatus()).getMsg();
            tradeSelectOrderResultDto.setCode(code);
            tradeSelectOrderResultDto.setMsg(msg);
            tradeSelectOrderResultDto.setTxNo(tradeOrder.getTxNo());
            return tradeSelectOrderResultDto;
        }
    }
}
